package org.or5e.api.bm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import org.or5e.api.bm.BulkMailConfig.ATTRIB_KEY;
import org.or5e.api.bm.server.SMTPServer;
import org.or5e.core.BaseException;
import org.or5e.core.BaseObject;
import org.or5e.core.BaseUtils;

public class BulkMailSPI extends BaseObject implements BulkMail {
    //private final static BulkMailContext context 			= new BulkMailContext();

    private HashMap<Double, CampaignThread> campaignList = new HashMap<Double, CampaignThread>();
    private Boolean initilized = Boolean.FALSE;
    private BulkMailConfig config = null;
    private BulkMailSecurityManager security = null;

    public BulkMailSPI() {
        Runtime.getRuntime().addShutdownHook(new MyShutdownHook());
        info("Bulk Mail Service Staring up.");
    }

    @Override
    public boolean addServer(double sessionID, SMTPServer server)
            throws BulkMailException {
        checkNotInitilized();
        if (security == null) {
            throw new BulkMailException(BulkMailConstants.S001);
        }
        security.checkAddServer();

        CampaignThread campaign = getCampaign(sessionID);
        campaign.addServer(server);
        return false;
    }

    @Override
    public boolean removeServer(double sessionID, SMTPServer server) throws BulkMailException {
        checkNotInitilized();
        CampaignThread campaign = getCampaign(sessionID);
        campaign.removeServer(server);
        return false;
    }

    @Override
    public ArrayList<SMTPServer> getServerList(double sessionID)
            throws BulkMailException {
        checkNotInitilized();

        CampaignThread campaign = getCampaign(sessionID);
        return campaign.getServerList();
    }

    @Override
    public BulkMailStatus getStatus(double sessionID) throws BulkMailException {
        checkNotInitilized();
        return null;
    }

    @Override
    public void init(BulkMailConfig config) throws BulkMailException {
        checkInitilized();
        setSecurityManager(new BulkMailSecurityManager());
        security.checkInit();


        try {
            String[] fileNames = BaseUtils.getUtility().validateEmail(config);
            info("Validate Email is Done.");

            config.setAttribute(ATTRIB_KEY.GOODFILE, new File(fileNames[0]));
            config.setAttribute(ATTRIB_KEY.BADFILE, new File(fileNames[1]));

            this.initilized = true;
            this.config = config;
            info("Initilization of Service is done.");
        } catch (FileNotFoundException e) {
            debug("Initilzation Failed....");
            error(e.getMessage());
        } catch (IOException e) {
            debug("Initilzation Failed....");
            error(e.getMessage());
        }
    }

    @Override
    public void pauseCampaign(double sessionID) throws BulkMailException {
        checkNotInitilized();
        // Not Been Planned for First Iteration
    }

    @Override
    public void resumeCampaign(double sessionID) throws BulkMailException {
        checkNotInitilized();
        // Not Been Planned for First Iteration
    }

    @Override
    public void setLogger(OutputStream outStream) throws BulkMailException {
        checkNotInitilized();
        // Not Been Planned for First Iteration
    }

    @Override
    public double startCampaign(String campaignName) throws BulkMailException {
        checkNotInitilized();
        CampaignThread campaign = new CampaignThread(campaignName, this.config, this);
        Double sessionID = new Double(Math.random());
        campaignList.put(sessionID, campaign);
        campaign.start();
        return sessionID;
    }

    @Override
    public void stopCampaign(double sessionID) throws BulkMailException {
        checkNotInitilized();
        CampaignThread campaign = getCampaign(sessionID);
        campaign.stopThread();
    }

    @Override
    public void setSecurityManager(BulkMailSecurityManager security) {
        this.security = security;
    }

    @Override
    public String getName() {
        return "BulkMailSPI";
    }

    private void checkInitilized() throws BulkMailException {
        if (initilized) {
            throw new BulkMailException(BulkMailConstants.E002);
        }
    }

    private void checkNotInitilized() throws BulkMailException {
        if (security == null) {
            throw new BulkMailException(BulkMailConstants.S001);
        }
        if (!initilized) {
            throw new BulkMailException(BulkMailConstants.E001);
        }
    }

    private CampaignThread getCampaign(Double sessionID) {
        return campaignList.get(sessionID);
    }

    public void shutdown() {
        Set<Double> sessions = campaignList.keySet();
        for (Double session : sessions) {
            CampaignThread campaign = getCampaign(session);
            campaign.stopThread();
            info("Campaign " + campaign.campaignName + " is Stopped");
        }
        info("Bulk Mail Service Shutting Down.");
    }

    private class MyShutdownHook extends Thread {

        @Override
        public void run() {
            shutdown();
        }
    }

	@Override
	public void install() throws BaseException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void uninstall() throws BaseException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void start() throws BaseException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void stop() throws BaseException {
		// TODO Auto-generated method stub
		
	}
}
